import xTableData from './xTableData.js';
import {replaceByObj, format,
    dateFormat, jsonToCsv, saveAsCsv, saveAsXmlXls,removeSubs,addSubs} from "./xUtil.js";
import {expandNodeByCode,checkNodeByCode,getArrayOfTreeNode,
    expandInit,getAllChildren,getAllParent} from "./treeUtil.js";
import xFilter from "./xFilter.js";
import xmlTable from "./xmlTable.js";
import xID from './xID.js';
import cell from './cell.js';
import xPagination from './xPagination.js';
import xAlert from "./xAlert.js";
import xSpin from "./xSpin.js";


const tmplBase = `
	    <div  class = "{{class}}" > 
	        <div type="main">
		       <table> 
		          <colgroup></colgroup>
		          <thead ></thead> 
		          <tbody ></tbody>
		       </table>
		    </div>
		    <div type="footer" style="display: none"></div>
		    <div type="filter-panel" style="position: absolute;z-index:150; display: none"></div>  
		</div> `;

const tmplTd ='<td {{colspan}} {{rowspan}} {{class}} {{row}} {{col}} {{type}}>{{html}}</td>';
const tmplTr= '<tr>{{html}}</tr>';

// const tmplExportItem =`<a type="export-icon" data-code="{{dataCode}}" {{hint}}>{{icon}}</a>`;

export default class xTable {

	/* 定义变量 开始*/
	$root;
	$main;
	$thead;
	$tbody;
	$footer;
    vIsTreeTable;
    vTableId = xID.getID();
	vTableData;
	vRownum = 1;
	//{key, type:asc|desc|no}
	vSortKey={};
	vFilter;
	vOldCols;
	vCheckKey;
	vStickyWidth;
	vStickyHeight;
	//{left:[],left-after},{right:[],right-before}
	vSticky={};
	//checkbox ,radio选中的数据 记录数据的地址。
	/*定义变量 结束*/
    vSelfEvent ={};
	// 构造函数
	constructor(cfg) {
		this.$root = $('#'+cfg.el);
		this.$root.html(tmplBase.replace('{{class}}',cfg.style||'xtable'));
        this.vCfg =cfg;
        this.setOldCols();
        this.vIsTreeTable = this.vCfg.cols[0].type=='tree'?true:false;
        this.init();
        this.vTableData =  new xTableData();
        this.refresh('All');
	};

	init(){
        this.$table = this.$root.find('[type="main"] table');
        this.$thead = this.$table.find('thead');
        this.$tbody = this.$table.find('tbody');
        this.vFilter = new xFilter(this.$root.find('[type="filter-panel"]'));
        this.$footer = this.$root.find('[type="footer"]');
        this.$root.on('click', '[type="tree-expand"]', this.evTreeExpand.bind(this));
        this.$root.on('click', '[type="tree-check"]', this.evTreeCheck.bind(this));
        this.$root.on('click', 'i[type="expand"]', this.evExpand.bind(this));
        this.$thead.on('click', 'i[type="filter"]', this.evFilter.bind(this));
        this.$tbody.on('click', 'span[type="status-switch"]',this.evSwitch.bind(this));
        this.$tbody.on('click', 'span[type="status-button"]',this.evStatusButton.bind(this));
        this.$thead.on('click', 'i[type="sort"]', this.evSort.bind(this));
        this.$root.on('click', 'input[type="checkbox"][table-select]', this.evCheckbox.bind(this));
        this.$root.on('click', 'input[type="radio"][table-select]', this.evRadio.bind(this));
        this.$footer.on('click','.page-link',this.evPageIndex.bind(this));
        this.$footer.on('change','select',this.evPageSizeChange.bind(this));
        this.$root.on('click','span[type="button"],button [type="button"]',this.evButton.bind(this));
        this.$table.on('click','.cell',this.evCellClick.bind(this));

        //注册自定义事件
        this.regEventOfCol();

    }

    regEventOfCol(){
	    for(let col of this.vCfg.cols){
	        if(col.event){
	            for(let btnKey in col.event)
                    this.vSelfEvent[btnKey] = col.event[btnKey];
            }
        }

        for(let btnKey in this.vSelfEvent){
            this.$table.on('click','[btn-key="'+btnKey+'"]',this.evBtnKeyClick.bind(this));
        }
    };


    //这个有问题
    setStickyData(){
        let $trs = this.$thead.find('tr');
        $trs.each((i,tr)=>{
            // tr 是 dom 对象
            for(let td of tr.childNodes){
                if(!this.vStickyHeight[i] || this.vStickyHeight[i]> td.offsetHeight)
                    this.vStickyHeight[i]= td.offsetHeight;
            }
        });

        // td 宽度通过tbody 的td 来获取 忽略span
        if(this.$tbody[0] && this.$tbody[0].childNodes[0]){
            let j =0;
            for(let td of this.$tbody[0].childNodes[0].childNodes){
                if(!this.vStickyWidth[j] || this.vStickyWidth[j]> td.offsetWidth)
                    this.vStickyWidth[j]= td.offsetWidth;
                //j +=getCellSpanByDom(td).colspan;
                j +=1;
            }
        }

    }

    //宽度或者长度累加数据
    getStickyAccuData(array,i,type){
	    let accu =0;
	    switch(type){
            case 'right':
                for(let k=array.length-1;k>i;k--){
                    accu +=array[k];
                }
                break;
            case 'left':
                for(let k=0;k<i;k++){
                    accu +=array[k];
                }
                break;
            default:
                for(let k=0;k<i;k++){
                    accu +=array[k];
                }
        }
        return accu+'px';
    }

    setOldCols(){
	    this.vOldCols = this.vCfg.cols;
    }

    getOldCols(){
	    return this.vOldCols;
    }

    setCols(){
	    let cols =[];
	    for(let o of this.vOldCols){
	        if(o.show !=0)
	            cols.push(o);
        }
        this.vCfg.cols= cols;
    };

    setSticky(){
	    if(this.vCfg.fixed || this.vSticky.left || this.vSticky.right){
            this.setStickyData();
            this.setZindex();
            if(this.vSticky.left)
                this.setLeftStickyStyle();
            if(this.vSticky.right)
                this.setRightStickyStyle();
            if(this.vCfg.fixed)
                this.setTopStickyStyle();
        }
    }

    setStickyCfg(){
        this.vStickyWidth=[];
        this.vStickyHeight=[];
        //{left:[],left-after},{right:[],right-before}
        this.vSticky={};
	    for(let i=0;i<this.vTableData.vKeys.length;i++){
	        if(this.vTableData.vKeys[i].fixed=='left'){
	            if(!this.vSticky.left)
	                this.vSticky.left=[];
                this.vSticky.left.push(this.vTableData.vKeys[i])
                if(i+1<this.vTableData.vKeys.length &&  !this.vTableData.vKeys[i+1].fixed)
                    this.vSticky.after = this.vTableData.vKeys[i+1];
            }

            if(this.vTableData.vKeys[i].fixed=='right'){
                if(!this.vSticky.right)
                    this.vSticky.right=[];
                this.vSticky.right.push(this.vTableData.vKeys[i])
                if(i>0 &&  !this.vTableData.vKeys[i-1].fixed)
                    this.vSticky.before = this.vTableData.vKeys[i-1];
            }
        }

        if(this.vSticky.right)
            this.vSticky.right.reverse();
    }
    /*
    * 固定表头 和 行 列 相当于 Zindex 要设置不同的值
    *  重叠区域 要设置 最大  比如 左上  ，右上
    * */
    setZindex(){
	    let ZIndex =100 ;
	    let ZTopIndex= 100+((this.vSticky.left &&this.vSticky.left.length)?this.vSticky.left.length:0)
           +((this.vSticky.right && this.vSticky.right.length)?this.vSticky.right.length:0);
	    let ZTopLeftIndex  =ZTopIndex+this.vTableData.vHeadMatrix.length;
	    if(this.vSticky.left){
            for(let key of this.vSticky.left){
                key._ZIndex = ZIndex;
                key._ZTopIndex = ZTopLeftIndex;
                ZIndex +=1;
                ZTopLeftIndex +=1;
            }
        }

        if(this.vSticky.right){
            for(let key of this.vSticky.right){
                key._ZIndex = ZIndex;
                key._ZTopIndex = ZTopLeftIndex;
                ZIndex +=1;
                ZTopLeftIndex +=1;
            }
        }

        this.vSticky.ZTopIndex=ZTopIndex;
    }

    setTopStickyStyle(){
        let $trs = this.$thead.find('tr');
        $trs.each((i,tr)=>{
            // tr 是 dom 对象
            for(let td of tr.childNodes){
                let isOverlay = td.classList.contains('fix-left') || td.classList.contains('fix-right');
                let index =td.getAttribute("col")-0;
                let row =td.getAttribute("row")-0;
                this.renderSticky(td,
                    {"z-index":isOverlay?(this.vTableData.vKeys[index]._ZTopIndex+row):(this.vSticky.ZTopIndex-row),
                        top:this.getStickyAccuData(this.vStickyHeight,i)})
            }
        });
	}

	setLeftStickyStyle(){
	    let $tds = this.$table.find('.fix-left');
	    $tds.each((i,td)=>{
	        //get col index
            let index =td.getAttribute("col")-0;
            this.renderSticky(td,{"z-index":this.vTableData.vKeys[index]._ZIndex,
                left:this.getStickyAccuData(this.vStickyWidth,index,'left')})
        })
    }

    setRightStickyStyle(){
        let $tds = this.$table.find('.fix-right');
        $tds.each((i,td)=>{
            //get col index
            let index =td.getAttribute("col")-0;
            this.renderSticky(td,{"z-index":this.vTableData.vKeys[index]._ZIndex,
                right:this.getStickyAccuData(this.vStickyWidth,index,'right')})
        })
    }

    refresh(type){
	    switch(type){
            case 'All':
                //this.vCfg.select ='';
                this.setCols();
                this.vTableData.prepare(this.vCfg);
                /*if(this.vCfg.pagination)
                    this.vCfg.pagination.pageIndex = 1;*/
                this.renderColgroup();
                this.renderHead();
                this.renderBody();
                this.renderSelect();
                this.renderFooter();
                break;
            case 'Data&Body&Footer':
                this.setCols();
                this.vTableData.prepare(this.vCfg);
                this.renderBody();
                this.renderSelect();
                this.renderFooter();
                break;
            case 'Body':
                this.renderBody();
                this.renderSelect();
                break;
            default:
                this.vCfg.select ='';
                this.setCols();
                this.vTableData.prepare(this.vCfg);
                /*if(this.vCfg.pagination)
                    this.vCfg.pagination.pageIndex = 1;*/
                this.renderColgroup();
                this.renderHead();
                this.renderBody();
                this.renderSelect();
                this.renderFooter();
        }
        if(this.vCfg.data && this.vCfg.data.length>0){
	        this.setStickyCfg();
            this.setSticky();
        }
    }

    renderColgroup(){
        if(this.vCfg.colgroup){
            let col;
            let colHtml ='';
            for(let group of this.vCfg.colgroup){

                col = ' ';
                for(let key in group){
                    col += (key+'="'+group[key]+'" ');
                }
                colHtml += '<col'+col+' >';
            }
            let $colgroup = this.$table.find('colgroup');
            $colgroup.html(colHtml);
        }
    }

    renderHead(){
        let trs ='';
        // 如果不显表头 ，直接退出
        if(this.vCfg.showHead==false){
            this.$thead.html(trs);
            return;
        }
        let tds;
        let renderTimes = this.vTableData.vHeadMatrix[0][0]._rendered;
        renderTimes=renderTimes?renderTimes+1:1;
        for(let i=0;i<this.vTableData.vHeadMatrix.length;i++){
            tds ='';
            //let j=0;
            for(let j=0;j<this.vTableData.vHeadMatrix[i].length;j++){
                let key = this.vTableData.vHeadMatrix[i][j];
                if(!(key._rendered==renderTimes)){
                    tds += this.renderHeadTd(key,i+','+j);
                    key._rendered = renderTimes;
                }
            }
            trs += tmplTr.replace('{{html}}',tds);
        }
        this.$thead.html(trs);
    }

    renderBody(){
        let trs = '';
        let tds;
        let hasExpand;
        let expandKey;
        let expandIndex;
        let group ='';
        let groupKey =this.vCfg.group;
        this.vRownum = 0;
        for(let i=0;i<this.vTableData.vDataMatrix.length;i++){

            //console.log(this.vTableData.vDataMatrix);
            //先分组

            if(groupKey){
                let gItem;
                for(let item of this.vTableData.vDataMatrix[i]){
                    if(item){
                        gItem = item;
                        break;
                    }
                }
                if(group !=gItem.item[groupKey]){
                    group = gItem.item[groupKey];
                    let groupHtml;
                    if(this.vCfg.groupRender)
                        groupHtml = this.vCfg.groupRender(this.vCfg.data,groupKey,group);

                    let gTd  = replaceByObj(tmplTd,{colspan:'colspan="'+this.vTableData.vKeys.length+'"',
                        rowspan:'',type:'type="table-group"',class:'',col:'',row:'',
                        html:groupHtml||cell.renderData({data:group,align:'left'})});
                    trs += tmplTr.replace('{{html}}',gTd);
                }
            }

            this.vRownum += 1;
            // 判断 这行 是否要显示
            tds ='';

            if(this.vIsTreeTable && (this.vTableData.vDataMatrix[i][0].item._show==false ||
                    this.vTableData.vDataMatrix[i][0].item._filter==false)){
                continue;
            }

            hasExpand = false;
            let dItem;
            for(let j=0;j<this.vTableData.vKeys.length;j++){
                dItem = this.vTableData.vDataMatrix[i][j];
                // 为空 说明是被合并的单元格
                if(dItem){
                    tds += this.renderTd(dItem,i+','+j);
                    //是否有 expand
                    if (dItem.item._expandMore == j){
                        hasExpand = true;
                        expandKey = dItem.key;
                        expandIndex =i;
                    }
                }
            }
            trs += tmplTr.replace('{{html}}',tds)
            //判断 这行 是否 是expand
            if(hasExpand){
                let tmpTd = replaceByObj(tmplTd,{colspan:'colspan="'+this.vTableData.vKeys.length+'"',
                    rowspan:'',type:'type="table-expand-more"',class:'',col:'',row:'',
                    html:this.renderExpandMore(this.vTableData.vDataMatrix[expandIndex][0],expandKey)})
                trs += tmplTr.replace('{{html}}',tmpTd);
            }
        }

        //是否最后一页 最后一页才需要加上汇总
        if(this.vCfg.pagination){
            let tmpData = this.vTableData.vAfterSortData||this.vTableData.vAfterFilterData||this.vTableData.vCfg.data;
            let maxNum =Math.ceil(tmpData.length/this.vCfg.pagination.pageSize);
            if(this.vCfg.pagination.pageIndex ==maxNum )
                trs += this.renderSum();
        }else{
            trs += this.renderSum();
        }

        this.$tbody.html(trs);
    }

    renderExpandMore(item,key,pos){
        return  key.callback(item.item,pos);
    }

    //处理汇总数据
    renderSum(){
	    let html='';
	    switch (typeof this.vCfg.summary){
	        case 'function':
	            html = this.vCfg.summary();
	            break;
            case 'object':
                html = this.renderSumByCfg();
                break;
        }
        return html;
    }

    renderSumByCfg(){
        let trs = '';
        let tds;
        for(let s of this.vCfg.summary){
            tds ='';
            for(let k of s){
                k.type = 'sum';
                tds +=this.renderTd({colspan:k.colspan,rowspan:k.rowspan,key:k},'-1,-1');
            }
            trs += tmplTr.replace('{{html}}',tds)
        }
        return trs;
    }

    renderHeadTd(key,pos){
        let row = pos.split(',')[0];
        let col = pos.split(',')[1];
        let [colspan,rowspan] = ['',''];
        let html = this.renderHeadCell(key,pos);
        let classHtml ='';
        if(this.vCfg.fixed)
            classHtml = 'fix-top';
        if(key.fixed)
            classHtml +=' fix-'+key.fixed;
        if(classHtml)
            classHtml = 'class="'+classHtml+'"';

        if(key && key._colspan && key._colspan>1 )
             colspan = 'colspan="'+key._colspan+'"';
        if(key && key._rowspan && key._rowspan>1)
            rowspan = 'rowspan="'+key._rowspan+'"';
        return replaceByObj(tmplTd,{colspan,rowspan,html,class:classHtml,datakey:'',
            row:'row="'+row+'"',col:'col="'+col+'"'});
    }

    //
    renderHeadCell(key,pos){
	    let html ='';
        // let [sortHtml,filterHtml,titleHtml]=['','',''];
        // let colType = item.type=='checkbox'?item.type: 'default';
        let cfg ={...key};
        cfg.type ="title";
        cfg.align = key.titleAlign;
        cfg.minwidth = key.width;
        cfg.style = '';
        switch (key.type){
            case 'checkbox':
                cfg.attr ="table-select";
                html = cell.renderCheckbox(cfg);
                this.vCheckKey = key.$data||'code';
                break;
            case 'radio':
                cfg.attr ="table-select";
                html = cell.renderTHead(cfg);
                this.vCheckKey = key.$data||'code';
                break;
            default:
                if(key.sort) {
                    if(key.$data == this.vSortKey.key)
                        cfg.sortType = this.vSortKey.type ;
                }
                if(key.filter)
                    cfg.filterActive =this.vTableData.isActiveFilter(key.$data);
                html = cell.renderTHead(cfg);
        }
        return html;
    }
    //
    renderTd(item,pos){
	    let row = pos.split(',')[0];
	    let col = pos.split(',')[1];
        let [colspan,rowspan] = ['',''];

        let classHtml ='';
        if(item.key.fixed)
            classHtml =' fix-'+item.key.fixed;
        if(classHtml)
            classHtml = 'class="'+classHtml+'"';

        let html =this.renderCell(item,pos);

        if(item &&  item.colspan>1 )
            colspan = 'colspan="'+item.colspan+'"';
        if(item &&  item.rowspan>1)
            rowspan = 'rowspan="'+item.rowspan+'"';

        return replaceByObj(tmplTd,{colspan,rowspan,html,class:classHtml,type:'',
            row:'row="'+row+'"',col:'col="'+col+'"'});
    }

    renderCell(item,pos){
        let data = item.item;
        let key = item.key;
        let html ='';
        let cfg ={};
        cfg.type= key.type;
        cfg.align = key.align;
        switch(key.type){
            case 'checkbox':
                cfg.code =  pos.split(',')[0];
                cfg.attr ="table-select";
                html =  cell.renderCheckbox(cfg);
                break;
            case 'radio':
                cfg.code =  pos.split(',')[0];
                cfg.radio = this.vTableId;
                cfg.attr ="table-select";
                html =  cell.renderRadio(cfg);
                break;
            case 'action':
                cfg.code =  pos;
                cfg.data= data;
                if(data._virtual)
                    cfg.button=[];
                else
                    cfg.button= key.button;
                html = cell.renderButton(cfg);
                break;
            case 'button':
                cfg.data= data;
                cfg.code =  pos;
                if(data._virtual)
                    cfg.button=[];
                else
                    cfg.button =  key.button;
                html =  cell.renderButton(cfg);
                break;

                /*case 'callback':
                cfg.code =  pos;
                cfg.data = item.item;
                html = cell.renderByCallback(cfg,key.callback);
                break;*/
            case 'progress':
                cfg.style = (typeof key.style =='function')?key.style(data,key):key.style;
                cfg.code = pos;
                cfg.data= data[key.$data];
                cfg.format = key.format;
                html = cell.renderProgress(cfg);
                break;
            case 'tag':
                cfg.code =  pos;
                cfg.data = data[key.$data];
                html = cell.renderTag(cfg);
                break;
            case 'rate':
                cfg.code =  pos;
                cfg.rate = data[key.$data];
                html = cell.renderRate(cfg);
                break;
            case 'expand':
                cfg.code =  pos;
                cfg._expandMore = data._expandMore==(pos.split(',')[1]-0);
                html = cell.renderExpand(cfg);
                break;
            case 'status':
                cfg.code = pos;
                cfg.switchLabel = key.switchLabel;
                cfg.data = data[key.$data];
                if(data._virtual)
                    html ='';
                else
                    html = cell.renderSwitch(cfg);
                break;
            case 'status-button':
                cfg.code = pos;
                cfg.statusLabel = key.statusLabel;
                cfg.data = data[key.$data];
                if(data._virtual)
                    html ='';
                else
                    html = cell.renderStatusButton(cfg);
                break;
            case 'tree':
                cfg.code = data.code;
                if(key.$link)
                    cfg.link = data[key.$link];
                 cfg.data = data.name||data.code;
                if(key.$badge)
                    cfg.badge = data[key.$badge];
                if(key.$icon)
                    cfg.icon = data[key.$icon];
                if(data._level)
                    cfg._level = data._level;
                if(key.checkbox){
                    cfg.checkable = true;
                    cfg._check = data._check;
                }
                if(data.children)
                    cfg.hasChildren = true;
                cfg._expand = data._expand;
                html = cell.renderTree(cfg);
                break;
            case 'text':
                cfg.code = pos;
                cfg.data = data[key.$data];
                html = cell.renderTextarea(cfg);
                break;
            case 'sum':
                if(typeof key.data=='function')
                    cfg.data = key.data(key);
                else
                    cfg.data= key.data;
                cfg.format = key.format;

                html=cell.renderData(cfg);
                break;
            case 'rownum':
                cfg.data= this.vRownum;
                cfg.code =  pos;
                cfg.type="data";
                cfg.style = key.style;
                html=cell.renderData(cfg);
                break;
            case 'data':
            default:
                if(key.render && (typeof key.render=='function')){
                    cfg.code =  pos;
                    cfg.data = item.item;
                    cfg.style = (typeof key.style =='function')?key.style(data,key):key.style;
                    cfg.format = key.format;
                    cfg.hint = key.hint;
                    html = cell.renderByCallback(cfg,key.render);
                }else {
                    cfg.style = (typeof key.style =='function')?key.style(data,key):key.style;
                    //console.log(key.style(data,key));
                    cfg.code =  pos;
                    cfg.type="data";
                    cfg.format = key.format;
                    cfg.hint = key.hint;
                    if(key.$link)
                        cfg.link = data[key.$link];
                    if(key.$data)
                        cfg.data = data[key.$data];
                    if(key.$badge)
                        cfg.badge = data[key.$badge];
                    if(key.$icon)
                        cfg.icon = data[key.$icon];

                    if(key.$image)
                        cfg.image = data[key.$image];
                    if(key.$hint)
                        cfg.hint = data[key.$hint];

                    if(key.$level)
                        cfg.level = data[key.$level];
                    html = cell.renderData(cfg);
                }

                break;
        }
        return html;
    }

    renderStyle(item,key){
        if(key.style){
            if(typeof key.style =='function')
                style = key.style(item);
            else
                style = key.style;
        }
        return replaceByObj(tmplItemStyle,{align,style});
    }

    renderFooter(){
        if(this.vIsTreeTable){
            this.$footer.hide();
            return ;
        }

        if(this.vCfg.pagination && (this.vCfg.ajaxTotal||(this.vCfg.data && this.vCfg.data.length>0))){
            let cfg ={...this.vCfg.pagination};
            let tmpData = this.vTableData.vAfterSortData||this.vTableData.vAfterFilterData||this.vTableData.vCfg.data;
            cfg.total = this.vCfg.pagination.ajaxTotal||tmpData.length;
            this.$footer.html(xPagination.render(cfg));
            this.$footer.show();
        }

    }

    renderSelect(){
        let key = this.vCheckKey;
       if(key && this.vCfg.select){
           let ss=this.vCfg.select.split(',');
           for(let i=0;i<this.vTableData.vData.length;i++){
               if (ss.includes(this.vTableData.vData[i][key]+'')){
                   let el = this.$tbody.find('div[data-code="'+i+'"] input[table-select]')[0];
                   el.checked= true;
               }
           }
       }
        //如果是checkbox 而且本页全部 checked  all 也要 checked
        this.verifyCheckAll();

    };

    renderSticky(td,style){
        for(let k in style){
            td.style[k] = style[k];
        }
    }

    evTreeExpand(e){
        let code = e.target.parentNode.getAttribute("data-code");
        expandNodeByCode(this.vTableData.vCfg.data,code);
        this.refresh('Body');
        if(this.vCfg.event && this.vCfg.event.OnTreeExpand)
            this.vCfg.event.OnTreeExpand(this.vTableData.vCfg.data,code);
    }

    evTreeCheck(e){
        let code = e.target.parentNode.getAttribute("data-code");
        checkNodeByCode(this.vTableData.vCfg.data,code);
        this.refresh('Body');
        if(this.vCfg.event.OnTreeCheck)
            this.vCfg.event.OnTreeCheck(this.vTableData.vCfg.data,code);
    }

    evExpand(e){
        let pos = e.target.parentNode.getAttribute("data-code").split(',');
        let index = pos[0];
        let item = this.vTableData.vDataMatrix[index][0].item;
        //如果相同说明 点击是本item  是全部收缩
        //如果不同说明是 点击其他的item expand
        if(item._expandMore == pos[1]-0)
            item._expandMore = -1;
        else
            item._expandMore = pos[1]-0;
        //item._expandMore= !item._expandMore;
        this.refresh("Body");
    }

    evButton(e){
        let dataIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[0];
        let keyIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[1];
        let buttonIndex =  e.currentTarget.getAttribute("index");
        // 获取key
        let key = this.vTableData.vKeys[keyIndex];
        let item = this.vTableData.vDataMatrix[dataIndex][0].item;
        if(key.button[buttonIndex].callback){
            key.button[buttonIndex].callback(item,this,e);
        }
    }

    evSwitch(e){
        let $e = $(e.currentTarget);
        if($e.hasClass("loading")){
            return;
        }
        let dataIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[0];
        let keyIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[1];
        // 获取key
        let key = this.vTableData.vKeys[keyIndex];
        let item = this.vTableData.vDataMatrix[dataIndex][0].item;
        if(item[key.$data] && this.vIsTreeTable && item.children){
            let children = getAllChildren(item);
            for(let c of children){
                if(c[key.$data]){
                    xAlert.error("存在启用的下级节点,此节点不能被停用!");
                    return;
                }

            }
        }

        if(!item[key.$data] && this.vIsTreeTable && item._parent){
            let parents = getAllParent(item);
            for(let p of parents){
                if(p[key.$data]==0){
                    xAlert.error("存在停用的上级节点,请先启用上级节点!");
                    return;
                }
            }
        }

        function cbSuccess(){
            $e.removeClass("loading");
            let switchLable =(key.switchLable||'停用,启用').split(",");
            item[key.$data] = (item[key.$data]==1?0:1);
            if(item[key.$data]){
                $e.addClass("checked");
                //console.log(e.currentTarget.childNodes[0]);
                e.currentTarget.children[0].innerHTML = switchLable[1];
            }else{
                $e.removeClass("checked");
                e.currentTarget.children[0].innerHTML = switchLable[0];
            }
        }

        if(key.callback){
            $e.removeClass("checked");
            $e.addClass("loading");
            key.callback(item,cbSuccess);
        }
    }

    // 暂时不用于tree table
    evStatusButton(e){
        let _this = this;
        let $e = $(e.currentTarget);
        if($e.hasClass("loading")){
            return;
        }
        let dataIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[0];
        let keyIndex = e.currentTarget.parentNode.getAttribute("data-code").split(',')[1];
        // 获取key
        let key = this.vTableData.vKeys[keyIndex];
        let item = this.vTableData.vDataMatrix[dataIndex][0].item;

        function cbSuccess(){
            item[key.$data] = (item[key.$data]==1?0:1);
            _this.refresh("Body");
        }

        if(key.callback){
            $e.removeClass("checked");
            $e.addClass("loading");
            key.callback(item,cbSuccess);
        }
    }

    evFilter(e){
        let index = e.target.parentNode.parentNode.getAttribute("col") ;
        let field = this.vTableData.vKeys[index].$data;
        let filterCfg ={
            data:this.vTableData.getKeySet(field),
            select:this.vTableData.getSelectByField(field),
            field,
            ok:this.filterOk.bind(this)
        };
        this.vFilter.show(filterCfg,this.$root ,$(e.target));
    }

    // 过滤后的回调函数
    filterOk(field,select,allChecked){
        if(allChecked==1)
            delete this.vTableData.vFilterKeys[field];
        else
            this.vTableData.addSelect(field,select);
        this.vTableData.filter();
        if(this.vCfg.pagination)
            this.vCfg.pagination.pageIndex=1;
        this.refresh('All');
    }

    evSort(e){
        let index = e.target.parentNode.parentNode.getAttribute("col") ;
        let field = this.vTableData.vKeys[index].$data;
        if(this.vSortKey.key==field){
            switch (this.vSortKey.type){
                case 'asc':
                    this.vSortKey.type= 'desc'
                    break;
                case 'desc':
                    this.vSortKey.type= 'no'
                    break;
                default:
                    this.vSortKey.type= 'asc'
            }
        }else{
            this.vSortKey ={};
            this.vSortKey.key = field;
            this.vSortKey.type = 'asc';
        }
        if(this.vCfg.pagination)
            this.vCfg.pagination.pageIndex=1;

        if(this.vCfg.ajax){
            this.ajax();
        }else{
            this.vTableData.vSortKey = this.vSortKey;
            this.refresh('All');
        }

    }

    evCheckbox(e){

        let code = e.target.parentNode.getAttribute("data-code")??'-1' ;
        let keyIndex = e.target.parentNode.parentNode.getAttribute("col");
        let key = this.vTableData.vKeys[keyIndex].$data;
        if(!key)
            key = 'code';

        let checked = e.target.checked;
        let array=[];
        //全选
        if(code =="-1"){
            this.$root.find('input[table-select]').each((index,item) =>{
                item.checked = checked;
            })
            this.vTableData.vData.forEach(data => array.push(data[key]));
        }else
            array.push(this.vTableData.vData[code][key]);

        if(checked)
            this.vCfg.select= addSubs(this.vCfg.select,array.join(','));
        else
            this.vCfg.select= removeSubs(this.vCfg.select,array.join(','));

        this.verifyCheckAll();

        //事件回调
        if(this.vCfg.event && this.vCfg.event.OnSelectAll && code=="-1")
            this.vCfg.event.OnSelectAll(checked,this.vCfg.select);

        if(this.vCfg.event && this.vCfg.event.OnSelect && code !="-1")
            this.vCfg.event.OnSelect(checked,this.vTableData.vData[code][key],this.vCfg.select);
    }

    evRadio(e){
        let code = e.target.parentNode.getAttribute("data-code") ;
        let keyIndex = e.target.parentNode.parentNode.getAttribute("col");
        let key = this.vTableData.vKeys[keyIndex].$data;
        if(!key)
            key = 'code';
        this.vCfg.select=this.vTableData.vData[code][key];
        //事件回调
        if(this.vCfg.event && this.vCfg.event.OnSelect)
            this.vCfg.event.OnSelect(this.vCfg.select);
    }

    cbAjaxSuccess(res){
        this.vCfg.ajaxStatus = "over";
        if(res.data1 && res.data1.total && this.vCfg.pagination)
            this.vCfg.pagination.ajaxTotal = res.data1.total;
        this.setData(res.data);
        xSpin.close();
    }


    evPageIndex(e){
        let tmp = e.target.innerHTML;
        switch(tmp){
            case "«":
                this.vCfg.pagination.pageIndex= 1;
                break;
            case "»":
                let tmpData = this.vTableData.vAfterSortData||this.vTableData.vAfterFilterData||this.vTableData.vCfg.data;
                let total = this.vCfg.pagination.ajaxTotal||tmpData.length;
                this.vCfg.pagination.pageIndex= Math.ceil(total/this.vCfg.pagination.pageSize);
                break;
            default:
                this.vCfg.pagination.pageIndex = parseInt(tmp);
        }
        if(this.vCfg.ajax && this.vCfg.ajaxStatus!='start'){
            this.ajax();
        }else
            this.refresh('Data&Body&Footer');


    }

    evPageSizeChange(e){
        this.vCfg.pagination.pageSize = parseInt(e.target.value);
        this.vCfg.pagination.pageIndex = 1;

        if(this.vCfg.ajax && this.vCfg.ajaxStatus!='start'){
            this.ajax();
        }else
            this.refresh('Data&Body&Footer');
    }

    evCellClick(e){
        if(this.vCfg.event && this.vCfg.event.OnCellClick){
            let row = e.currentTarget.parentNode.getAttribute("row");
            let col = e.currentTarget.parentNode.getAttribute("col");
            this.vCfg.event.OnCellClick(this.vTableData.vData[row],row,col,e);
        }
    }

    evBtnKeyClick(e){

        let btnKey = e.target.getAttribute("btn-key");
        let dataIndex = e.target.parentNode.getAttribute("data-code").split(',')[0];
        let keyIndex = e.target.parentNode.getAttribute("data-code").split(',')[1];
        // 获取key
        let key = this.vTableData.vKeys[keyIndex];
        let item = this.vTableData.vDataMatrix[dataIndex][0].item;

         if(this.vSelfEvent[btnKey]){
             this.vSelfEvent[btnKey](item,key,this,e);
         }
    }

    /*
    *  checkbox  同步
    *  全选 和 表中 所有 的 checkbox 状态同步
    * */
    verifyCheckAll(){
        let checkboxCnt = this.$tbody.find('input[table-select]').length;
        let checkedCnt = this.$tbody.find('input[table-select]:checked').length;
        if(checkboxCnt){
            if(checkboxCnt != checkedCnt){
                this.$thead.find('input[table-select]')[0].checked = false;
            }else{
                this.$thead.find('input[table-select]')[0].checked = true;
            }
        }
    }

    ajax(){
        xSpin.pop(this.$tbody);
        this.vCfg.ajaxStatus = "start";
        let sortKey ='',sortType = '';
        if(this.vSortKey.type!='no' && this.vSortKey.key){
            sortKey=this.vSortKey.key;
            sortType = ' '+this.vSortKey.type;
        }
        this.vCfg.ajax({index: (this.vCfg.pagination.pageIndex-1)*this.vCfg.pagination.pageSize,
            offset:this.vCfg.pagination.pageSize,
            sortKey,sortType},this.cbAjaxSuccess.bind(this));
    };

    setStyle(style){
        this.$root.attr('class',style);
    }

    setData(data){
        this.vCfg.data= data;
        this.refresh("All");
    }

    getSelect(){
        return this.vCfg.select;
    }

    getSelectDetail(){
        let select = [];
        let tData = this.getTableData();
        let selectKey;
        for(let c of this.vCfg.column){
            if(['radio','checkbox'].includes(c.type)){
                selectKey=c;
                break;
            }
        }
        if(tData){
            let selected = this.vCfg.select.split(',') ;
            for(let d of tData){
                if(selected.includes(d[selectKey.$data||'code']+''))
                    select.push(d);
            }
        }
        if(selectKey && selectKey.type =='checkbox')
            return select;
        else
            return select[0];
    }

    getTableData(){
        if(this.vTableData.vAfterSortData && this.vTableData.vAfterSortData.length>0 )
            return this.vTableData.vAfterSortData;
        else if(this.vTableData.vAfterFilterData && this.vTableData.vAfterFilterData.length>0)
            return this.vTableData.vAfterFilterData;
        else return this.vTableData.vCfg.data;
    }

    getTreeSelect(){
        let select=[];
        this.vTableData.vData.forEach(data => {
            if(data._check>0)
                select.push(data);
        })
        return select;
    }

    saveCsv(fileName){
        saveAsCsv(fileName+'.csv',jsonToCsv(json));
    }

    saveXls(fileName){
        saveAsXmlXls(fileName+'.xls',new xmlTable().toXmlTable(this.$table));
    }

    setSelect(select){
        this.vCfg.select= select;
        this.renderSelect();
    }

    addSelect(codes){
        if(!this.vCfg.select)
            this.vCfg.select ='';
        addSubs(this.vCfg.select,codes);
    }

    selectAll(){
        let select =[];
        for(let i =0 ;i<this.vCfg.data.length;i++){
            select.push(this.vCfg.data[i].code);
        }
        this.vCfg.select = select.join(',');
        this.renderSelect();
    }

    treeExpand(expand){
        expandInit(this.vTableData.vData,expand);
        this.refresh('body');
    }

    treeCheck(codes){
        let array =codes.split(',');
        array.forEach(code =>
            checkNodeByCode(this.vTableData.vCfg.data,code)
        )
        this.refresh('Body');
    }

    exportXls(){
        let fileName = dateFormat(new Date(),'yyyyMMddhhmm');
        saveAsXmlXls(fileName+'.xls',new xmlTable().toXmlTable(this.$table));
    }

    exportCsv(){
        let fileName = dateFormat(new Date(),'yyyyMMddhhmm');
        let json = this.vIsTreeTable?getArrayOfTreeNode(this.vCfg.data):this.vCfg.data;
        saveAsCsv(fileName+'.csv',jsonToCsv(json));
    }
}